﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NSRE.Math;


namespace Mosos
{
    class WorldGenerator
    {
        const double FOOD_DENSITY = 0.03;
        const int MARGIN = 64;
        const double SPACE = 1.20;
        const double MAX_FOOD_SIZE_COEF = 0.80;

        static public List<Cell> generate_world(int world_size, AI_interface[] interfaces, int cell_size, MGraphics.World world)
        {
            int w_size_2 = world_size / 2;
            Cell[] cells = new Cell[interfaces.Length];
            double perim = 2 * Math.PI * w_size_2;
            int nb_cells = interfaces.Length;
            int cell_rad = cell_size;
            double alpha = 2 * Math.PI / (double)nb_cells;
            double angle = 0;
            int cell_idx = 0;
            double cluster_rad = (double)cell_rad * SPACE * 2.0 / (2.0 * Math.Sin(Math.PI / (double)nb_cells)); 

            // AIs
            while (angle < Math.PI * 2 && cell_idx < interfaces.Length)
            {
                angle += alpha;
                int x = (int)((double)w_size_2 + (double)cluster_rad * Math.Cos(angle));
                int y = (int)((double)w_size_2 + (double)cluster_rad * Math.Sin(angle));
                Vector2 pos = new Vector2(x, y);
                string name = "cell" + cell_idx;
                cells[cell_idx] = new Cell(pos, cell_rad, interfaces[cell_idx], name, world);
                cell_idx++;
            }
            List<Cell> cells_list = new List<Cell>(cells);


            // Food

           
            int box_size = (int)cluster_rad * 2 + cell_size + MARGIN;
            NSRE.Container.BoundingBox2 cell_box = new NSRE.Container.BoundingBox2();

            cell_box.Max_X = w_size_2 + box_size / 2;
            cell_box.Max_Y = w_size_2 + box_size / 2;
            cell_box.Min_X = w_size_2 - box_size / 2;
            cell_box.Min_Y = w_size_2 - box_size / 2;


            int inv_prob = (int)(1.0 / FOOD_DENSITY);
            double max_food_size = (double)cell_size * MAX_FOOD_SIZE_COEF;
            Random rand = new Random();
            int step = (int)(world_size / max_food_size);
            int count = 0;
            for (int pos_x = 0; pos_x < world_size; pos_x += step)
            {
                for (int pos_y = 0; pos_y < world_size; pos_y += step)
                {
                    if (!cell_box.Contain(pos_x, pos_y) && 
                        rand.Next() % inv_prob == 0)
                    {
                        int size_food = (int)(max_food_size * Math.Max(rand.NextDouble(), 0.5));
                        Vector2 diff = new Vector2(w_size_2 - pos_x - size_food , w_size_2 - pos_y-  size_food);
                        if (diff.Magnitude() + size_food - w_size_2 < 0)
                        {
                            Vector2 pos = new Vector2(pos_x, pos_y);
                            string name = "food" + count;
                            cells_list.Add(new Cell(pos, size_food, new AI_food(), name, world));
                            count++;
                        }
                    }
                }
            }
            return cells_list;
        }
    }
}
